// -------- WIFI -------- #include // -------- FIREBASE -------- #include #include "addons/TokenHelper.h" #include "addons/RTDBHelper.h" // -------- WIFI -------- const char* ssid = "MiCho"; const char* password = "Hello1234"; // -------- FIREBASE CONFIG -------- #define API_KEY "AIzaSyDpefz07KOuYyj0mZ1YtvJkm5g3z5HU0-I" #define DATABASE_URL "https://smart-piggy-effc6-default-rtdb.asia-southeast1.firebasedatabase.app/" FirebaseData fbdo; FirebaseAuth auth; FirebaseConfig config; // -------- PIN SETUP -------- #define BUTTON_PIN D8 #define LED_PIN D2 // -------- TIMING -------- const unsigned long debounceDelay = 50; const unsigned long longPressTime = 1000; const unsigned long doublePressGap = 400; // -------- FIREBASE TIMING -------- unsigned long lastFirebaseRead = 0; const unsigned long firebaseInterval = 2000; // -------- STATE -------- int totalAmount = 0; int goal = 0; int lastGoal = -1; // -------- BUTTON STATE -------- bool buttonState = LOW; bool lastButtonReading = LOW; unsigned long lastDebounceTime = 0; unsigned long pressStartTime = 0; unsigned long lastReleaseTime = 0; int pressCount = 0; // -------- SETUP -------- void setup() { Serial.begin(115200); pinMode(BUTTON_PIN, INPUT_PULLDOWN); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); Serial.println("Connecting to WiFi..."); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi Connected!"); Serial.println(WiFi.localIP()); config.api_key = API_KEY; config.database_url = DATABASE_URL; config.token_status_callback = tokenStatusCallback; Firebase.signUp(&config, &auth, "", ""); Firebase.begin(&config, &auth); Firebase.reconnectWiFi(true); Serial.println("Firebase ready"); } // -------- LOOP -------- void loop() { // -------- READ GOAL (ONLY IF CHANGED) -------- if (Firebase.ready() && millis() - lastFirebaseRead > firebaseInterval) { lastFirebaseRead = millis(); if (Firebase.RTDB.get(&fbdo, "/piggy/goal")) { int newGoal = 0; String type = fbdo.dataType(); if (type == "int") newGoal = fbdo.intData(); else if (type == "float") newGoal = (int)fbdo.floatData(); else if (type == "double") newGoal = (int)fbdo.doubleData(); else if (type == "string") newGoal = fbdo.stringData().toInt(); if (newGoal != lastGoal) { goal = newGoal; lastGoal = newGoal; Serial.print("Goal updated: "); Serial.println(goal); } } } // -------- BUTTON LOGIC -------- int reading = digitalRead(BUTTON_PIN); if (reading != lastButtonReading) { lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { if (reading != buttonState) { buttonState = reading; if (buttonState == HIGH) { pressStartTime = millis(); } else { unsigned long pressDuration = millis() - pressStartTime; if (pressDuration >= longPressTime) { handleLongPress(); pressCount = 0; } else { pressCount++; lastReleaseTime = millis(); } } } } if (pressCount > 0 && (millis() - lastReleaseTime) > doublePressGap) { if (pressCount == 1) { handleSinglePress(); } else if (pressCount == 2) { handleDoublePress(); } pressCount = 0; } lastButtonReading = reading; } // -------- BUTTON ACTIONS -------- void handleSinglePress() { addAmount(1); blinkLED(1); } void handleDoublePress() { addAmount(2); blinkLED(2); } void handleLongPress() { addAmount(5); digitalWrite(LED_PIN, HIGH); delay(400); digitalWrite(LED_PIN, LOW); } // -------- FIREBASE WRITE (SAFE: NO OVERWRITE) -------- void sendToFirebase(int total, int percentage, int lastCoin) { if (Firebase.ready()) { Firebase.RTDB.setInt(&fbdo, "/piggy/total", total); Firebase.RTDB.setInt(&fbdo, "/piggy/percentage", percentage); Firebase.RTDB.setInt(&fbdo, "/piggy/lastCoin", lastCoin); Firebase.RTDB.setInt(&fbdo, "/piggy/goal", goal); // keep goal synced Serial.println("Data updated (safe write)"); } } // -------- CORE LOGIC -------- void addAmount(int value) { totalAmount += value; int percentage = 0; if (goal > 0) { percentage = (totalAmount * 100) / goal; } Serial.print("Added: "); Serial.print(value); Serial.print(" | Total: "); Serial.print(totalAmount); Serial.print(" | "); Serial.print(percentage); Serial.println("%"); sendToFirebase(totalAmount, percentage, value); } // -------- LED -------- void blinkLED(int times) { for (int i = 0; i < times; i++) { digitalWrite(LED_PIN, HIGH); delay(120); digitalWrite(LED_PIN, LOW); delay(120); } }